#include "WZData.h"

////////////////////////////////////////////////////////////////
// Various functions to load stuff.
// You will only need wz::init and wz::load.
// Ignore the rest
////////////////////////////////////////////////////////////////
bool wz::init(string path) {
	WZLib::WZConfig::imageDir = path;
	WZLib::Init();
	return true;
}
bool wz::load(string name) {
	cout << "Loading " << name << ".wz" << endl;
	WZLib::WZFile* wz_file = new WZLib::WZFile(WZLib::WZConfig::imageDir+"\\"+name+".wz");
	if(wz_file->parse()!=0){
		cout << "Failed" << endl;
	}
	WZLib::WZDirectory* dir = wz_file->wzDir();
	wz::parse_dir(dir, &wz::top[name]);
	return true;
}
bool wz::parse_dir(WZLib::WZDirectory* dir, wz::node* cur_node) {
	WZLib::WZObjectCollection& stuff = dir->subDirs();
	for(unsigned int i=0;i<stuff.size();i++){
		WZLib::WZDirectory* item = (WZLib::WZDirectory*)(stuff[i]);
		string name = item->name();
		wz::parse_dir(item,&(*cur_node)[name]);
		//cout << name << endl;
	}
	WZLib::WZObjectCollection& stuff2 = dir->childImages();
	for(unsigned int i=0;i<stuff2.size();i++){
		WZLib::WZImage* item = (WZLib::WZImage*)(stuff2[i]);
		string name = item->name();
		name.erase(name.size()-4);
		wz::parse_img(item,&(*cur_node)[name]);
		//cout << name << endl;
	}
	return true;
}
bool wz::parse_img(WZLib::WZImage* dir, wz::node* cur_node) {
	cur_node->initf();
	cur_node->image = dir;
	return true;
}

bool wz::parse_sub(WZLib::WZSubProperty* dir, wz::node* cur_node) {
	WZLib::WZObjectCollection& stuff = dir->properties();
	for(unsigned int i=0;i<stuff.size();i++){
		WZLib::WZImageProperty* item = (WZLib::WZImageProperty*)(stuff[i]);
		//cout << item->typeName(item->propType()) << " " << item->name() << " " << endl;
		switch(item->propType()){
			case WZLib::WZImageProperty::Prop_Canvas:
				wz::parse_canvas((WZLib::WZCanvasProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_CompressedInt:
				wz::parse_int((WZLib::WZCompressedIntProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_Convex:
				wz::parse_convex((WZLib::WZConvexProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_Double:
				wz::parse_double((WZLib::WZDoubleProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_Extended:
				wz::parse_extended((WZLib::WZExtendedProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_Float:
				wz::parse_float((WZLib::WZFloatProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_MP3:
				break;
			case WZLib::WZImageProperty::Prop_Null:
				break;
			case WZLib::WZImageProperty::Prop_PNG:
				break;
			case WZLib::WZImageProperty::Prop_String:
				wz::parse_string((WZLib::WZStringProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_Sub:
				//cout << endl;
				wz::parse_sub((WZLib::WZSubProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_Unknown:
				//cout << endl;
				break;
			case WZLib::WZImageProperty::Prop_UnsignedShort:
				wz::parse_short((WZLib::WZUnsignedShortProperty*)item,&(*cur_node)[item->name()]);
				break;
			case WZLib::WZImageProperty::Prop_UOL:
				break;
			case WZLib::WZImageProperty::Prop_Vector:
				wz::parse_vector((WZLib::WZVectorProperty*)item,&(*cur_node)[item->name()]);
				break;
			default:
				//cout << endl;
				break;
		}
	}
	return true;
}
bool wz::parse_canvas(WZLib::WZCanvasProperty* dir, wz::node* cur_node) {
	//cout << endl;
	wz::parse_sub((WZLib::WZSubProperty*)dir,cur_node);
	(*cur_node)["width"] = (*dir->png())->width();
	(*cur_node)["height"] = (*dir->png())->height();
	cur_node->sprite_data(*dir->png());
	((sprite*)(*cur_node))->node(cur_node);
	return true;
}
bool wz::parse_int(WZLib::WZCompressedIntProperty* dir, wz::node* cur_node) {
	//cout << dir->value << endl;
	(*cur_node) = dir->value;
	return true;
}
bool wz::parse_convex(WZLib::WZConvexProperty* dir, wz::node* cur_node) {
	//cout << endl;
	wz::parse_sub((WZLib::WZSubProperty*)dir,cur_node);
	return true;
}
bool wz::parse_double(WZLib::WZDoubleProperty* dir, wz::node* cur_node) {
	//cout << dir->value << endl;
	(*cur_node) = dir->value;
	return true;
}
bool wz::parse_extended(WZLib::WZExtendedProperty* dir, wz::node* cur_node) {
	//cout << endl;
	return true;
}
bool wz::parse_float(WZLib::WZFloatProperty* dir, wz::node* cur_node) {
	//cout << dir->value << endl;
	(*cur_node) = dir->value;
	return true;
}
bool wz::parse_string(WZLib::WZStringProperty* dir, wz::node* cur_node) {
	//cout << dir->value << endl;
	(*cur_node) = dir->value;
	return true;
}
bool wz::parse_short(WZLib::WZUnsignedShortProperty* dir, wz::node* cur_node) {
	//cout << dir->value << endl;
	(*cur_node) = dir->value;
	return true;
}
bool wz::parse_vector(WZLib::WZVectorProperty* dir, wz::node* cur_node) {
	//cout << endl;
	//cout << "x ";
	wz::parse_int(dir->xprop,&(*cur_node)["x"]);
	//cout << "y ";
	wz::parse_int(dir->yprop,&(*cur_node)["y"]);
	return true;
}
////////////////////////////////////////////////////////////////
// wz::node
////////////////////////////////////////////////////////////////
wz::node::node() {
	realValue = 0;
	stringValue = "";
	spriteValue = new sprite;
	init = false;
	children = new map <std::string, wz::node>;
	parent = 0;
	image = 0;
	loaded = false;
}
wz::node::~node() {
	
}
wz::node& wz::node::operator [] (string key) {
	if(image && !loaded){
		if(&(*parent)[name]!=this){
			loaded = true;
			return (*parent)[name][key];
		}
		cout << "Loading img " << endl;
		image->parse(NULL);
		loaded = true;
		wz::parse_sub(image->sub(),this);
	}
	(*children)[key].parent = this;
	(*children)[key].name = key;
	return (*children)[key];
}
wz::node& wz::node::operator [] (const char* key) {
	return (*this)[string(key)];
}
map <std::string, wz::node>::iterator wz::node::begin() {
	return (*children).begin();
}
map <std::string, wz::node>::iterator wz::node::end() {
	return (*children).end();
}
wz::node::operator bool() {
	return init;
}
wz::node::operator double() {
	return realValue;
}
wz::node::operator int() {
	return (int)realValue;
}
wz::node::operator string() {
	return stringValue;
}
wz::node::operator sprite*() {
	spriteValue->node(this);
	return spriteValue;
}
void wz::node::operator = (double value) {
	realValue = value;
	init = true;
	if(parent){
		parent->initf();
	}
}
void wz::node::operator = (int value) {
	realValue = value;
	init = true;
	if(parent){
		parent->initf();
	}
}
void wz::node::operator = (string value) {
	stringValue = value;
	init = true;
	if(parent){
		parent->initf();
	}
}
void wz::node::operator = (sprite* value) {
	spriteValue = value;
	init = true;
	if(parent){
		parent->initf();
	}
}
void wz::node::operator = (wz::node& other) {
	if(children!=other.children && children->empty()){
		delete children;
	}
	children = other.children;
	realValue = other.realValue;
	stringValue = other.stringValue;
	if(spriteValue!=other.spriteValue){
		delete spriteValue;
	}
	spriteValue = other.spriteValue;
	parent = other.parent;
	image = other.image;
	loaded = other.loaded;
	name = other.name;
	init = true;
	if(parent){
		parent->initf();
	}
}
void wz::node::initf() {
	init = true;
	if(parent){
		parent->initf();
	}
}
void wz::node::sprite_data(WZLib::WZPNGProperty* png){
	spriteValue->data = png;
}

////////////////////////////////////////////////////////////////
// wz::top_node
////////////////////////////////////////////////////////////////
wz::top_node::top_node() {
	
}
wz::top_node::~top_node() {
	
}
wz::node& wz::top_node::operator [] (string key) {
	return children[key];
}
map <std::string, wz::node>::iterator wz::top_node::begin() {
	return children.begin();
}
map <std::string, wz::node>::iterator wz::top_node::end() {
	return children.end();
}
wz::top_node wz::top;